程序集加载与反射(一):理论篇

目录

  • 程序集加载
  • 获取类型信息
  • 构造类型实例
  • 通过反射发现成员
  • 调用成员

 

一、程序集加载

Load方法:CLR通过调用System.Rreflection.Assemblly类的静态方法来显示加载程序集。

public static Assembly Load(AssemblyName assemblyRef);
public static Assembly Load(string assemblyString);


LoadFrom方法:同样我们可以使用 远程加载程序集。此方法首先打开程序集,并通过 public static AssemblyName GetAssemblyName(string assemblyFile);方法提取到程序集名称,然后再会使用Load方法加载程序集。

public static Assembly LoadFrom(string path);

ReflectionOnlyLoad方法:加载程序集,只是获取程序集的相关信息。但CLR禁止此程序集中的代码执行。

public static Assembly ReflectionOnlyLoad(string assemblyString);

同样也有ReflectionOnlyLoadFrom

public static Assembly ReflectionOnlyLoadFrom(string path);

 

二、获取类型信息

1、System.Type.GetType方法

public static Type GetType(string typeName);

字符串必须执行的是全名,对于基元类型不能识别,识别CLR类型。

2、System.Type.ReflectionOnlyGetType

public static Type ReflectionOnlyGetType(string typeName, bool throwIfNotFound, bool ignoreCase);

只是显示反射上下文内容,不能够执行代码。

3、操作符typeof(),可以对类型进行晚期绑定并与早期绑定类型进行比对。

static Encryption(object o)
        {
             //早期绑定:o.GetTye()  
             //晚期绑定typeof
            if (o.GetType() == typeof(Encryption))
            {
            }
        }   

 

三、构造类型实例

1、System.Activator.CreateInstance

public static object CreateInstance(Type type);
public static ObjectHandle CreateInstance(string assemblyName, string typeName);

 上面的方法返回值有的是ObjectHandle类型,此类型允许将一个AppDomian中的对象传送到另一个AppDomian而且不需要具体化哪个对象。如果需要具体化具体的类型就可以调用 Unwrap()方法。

 2、System.Activator.CreateComInstanceFrom

public static ObjectHandle CreateComInstanceFrom(string assemblyName, string typeName);

程序集和类型都是字符串直接指定,不过,程序集需要使用LoadFrom方法来加载得到程序集,并且提取名称作为参数传递。当然对于返回值我们也需要调用Unwrap()进行具体化。

System.Reflection.Assembly assy= System.Reflection.Assembly.LoadFrom("");

System.Activator.CreateComInstanceFrom(assy.FullName, "Encryption");

 

四、通过反射发现成员

 层次结构

 因为Reflection.MemberInfo是成员结构层次的根,所以需要了解一下MemberInfo的成员组成:

 1、执行以下代码,区分一下DeclaringType和ReflectedType:

DeclaringType:声明方法的类;ReflectedType:当前的反射类

 public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            System.Reflection.MemberInfo[] mi = typeof(MyType).GetMembers();            

            foreach (var m in mi)
            {
               var dt=  m.DeclaringType;

               var rt = m.ReflectedType;
            }
        }
    }
    public sealed class MyType
    {

        public override string ToString()
        {
            return null;
        }
    }

ToSting()方法,因为声明它的类和当前所在的反射类是同一个即MyType。

Equal()方法,因为声明它的类是Object,但是当前反射类是MyType。

以上就是DeclaringType和ReflectedType的区别。

 

2、BindingFlags:筛选返回的成员种类

我们可以调用Type的 GetMethod、GetProperty、GetNestedType各种Get。我们可以组合BindingFlags,来筛选我们需要的东西。

 

五、调用成员的类型

我们可以找出我们需要的东东,然后我们可以进行调用。调用属性、方法、构造函数等等。

调用FieldInfo,可以获取或者设置字段的值;

调用ConstructorInfo,可以向构造传递实参,从而构造类型的一个实例;

调用MethodInfo,可以通过传递实参来调用方法,并返回它的返回值;

调用PropertyInfo,可以调用属性的get和set访问其方法。

 1、调用方法

public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, CultureInfo culture);

调用此方法可以在成员类型里搜索一个匹配的类型成员,如果没找到,抛出异常。如果找到,就会调用此成员。我们可以归纳以上行为为两个阶段:绑定和调用。

我们调用一个绑定器方法时,首先我们传递 目标成员 name、方法的所有参数类型 args 、指定的 BindingFlags invokeAttr 。

参数 name :目标成员。名字

参数 invokeAttr :这些位标识的组合可以帮助我们更好的定位我们的成员 IgnoreCase = 1, DeclaredOnly = 2,Instance = 4,Static = 8,Public = 16等

参数 binder :它的类型从System.Relflection.Binder 抽象类型派生的,从Binder派生的类型,封装了InverMember方法确定绑定类型的规则。编译器为我们定义了System.DefaultBinder 的实际类型可以为我们使用。可以帮助我们自动的类型转换。

参数 target : 目标成员所在类的实例的一个引用。静态类 =null。

参数 args: 传递的参数。

参数 culture: 如果有自己的绑定器可以使用此参数,如果前面参数使用了System.DefaultBinder,culture参数就可以省略了。

2、一次绑定,多次调用

我们利用Type的InvokeMember方法可以,访问任何成员。但是如果多次调用,我们就需要多次进行绑定并调用,比较损耗性能。我们可以使用:

 

  

posted @ 2015-06-23 22:10  K战神  阅读(3139)  评论(2编辑  收藏  举报